<script setup lang="ts">
import { menuApi } from "@/api/admin/menu";
import {
  ElDialog,
  ElForm,
  ElFormItem,
  ElTag,
  ElInput,
  ElButton,
  ElMessage,
  ElAutocomplete,
  ElRadioGroup,
  ElRadio,
  ElInputNumber,
  ElRow,
  ElCol,
  ElSwitch,
} from "element-plus";
import { MyIcon } from "@/components/MyIcon";
import { nextTick, onMounted, ref, unref } from "vue";
import MenuTree from "./MenuTree.vue";

class MenuForm {
  parentId: undefined | string = undefined;
  name: string | undefined = "";
  path = "";
  sort = 0;
  component: string | undefined = "";
  redirect = "";
  meta = {
    title: "",
    menuType: "",
    icon: "",
    hidden: 0,
  };
}
const componentPaths = ref<any>([]);

const menuForm = ref(new MenuForm());

const parentMenuTagTitle = ref("");

const menuFormRef = ref();

const visible = ref(false);

const menuTreeRef = ref<any>(null);

const props = defineProps({
  menuTree: {
    type: Array,
    default: false,
  },
});

const emit = defineEmits(["update"]);

const isEditor = ref(false);

// 获取所有组件
const modules = import.meta.glob("@/views/**/*.vue");

// 是否禁用菜单类型的修改
const disableMenuTypeChange = ref(false);

// 打开弹窗
const open = (data: any = null) => {
  // console.log(data);
  visible.value = true;
  if (data) {
    isEditor.value = true;
    // 如果有子菜单,不允许修改菜单类型
    if (data.children?.length > 0) {
      disableMenuTypeChange.value = true;
    } else {
      disableMenuTypeChange.value = false
    }
    if (data.parentId) {
      const parentMenu = findMenu(data.parentId, props.menuTree);
      parentMenuTagTitle.value = parentMenu.meta.title;
    }
    nextTick(() => {
      menuForm.value = data;
    });
  } else {
    isEditor.value = false;
    menuForm.value = new MenuForm();
  }
};

onMounted(() => {
  const keys = Object.keys(modules).map((item) => {
    const path = item.replace(/^\/src\/views(.*)\.vue$/, "$1");
    return {
      label: path,
      value: path,
    };
  });
  componentPaths.value = keys;
});

// 搜索组件路径
const SearchComponentPaths = (str: string) => {
  return componentPaths.value.filter((item: any) => {
    return item.label.includes(str);
  });
};

// 根据id查找菜单
const findMenu = (id: string, menuList: any[]): any => {
  let menu = null;
  menuList.find((item: any) => {
    if (item.id == id) {
      return (menu = item);
    }
    if (item.children) {
      const child = findMenu(id, item.children);
      if (child) {
        return (menu = child);
      }
    }
  });
  return menu;
};



// 清除表单值
const clearFormValue = () => {
  menuForm.value.parentId = "";
  menuFormRef.value.resetFields();
};

// 设置父级菜单
const setParentMenu = (menu: any) => {
  menuForm.value.parentId = menu.id;
  parentMenuTagTitle.value = menu.meta.title;
};

// 取消
const handleCancel = () => {
  clearFormValue();
  visible.value = false;
};

// 确定
const handleOk = async () => {

  // console.log(menuForm.value);

  await menuFormRef.value.validate();
  const menuType = menuForm.value.meta.menuType;
  const parentId = menuForm.value.parentId;

  if (!parentId) {
    if (menuForm.value.path.charAt(0) !== "/") {
      menuForm.value.path = "/" + menuForm.value.path
    }
  } else {
    const firstChar = menuForm.value.path.charAt(0);
    if (firstChar === "/") {
      menuForm.value.path = menuForm.value.path.slice(1);
    }
  }

  if (menuType === "url") {
    menuForm.value.component = undefined;
    menuForm.value.name = undefined;
  }
  if (menuType === "catalog") {
    if (parentId) {
      menuForm.value.component = undefined;
    } else {
      menuForm.value.component = "#";
    }
    // menuForm.value.name = undefined;
  }
  let ret = null;
  if (isEditor.value) {
    ret = await menuApi.updateRoleRoutesApi(menuForm.value);
  } else {
    ret = await menuApi.saveRoleRoutesApi(menuForm.value);
  }

  if (ret.code === 200) {
    clearFormValue();
    ElMessage.success(`${unref(isEditor) ? "修改" : "新增"}成功`);
    visible.value = false;
    emit("update");
  } else {
    ElMessage.error(ret.data.msg);
  }
};

// 关闭弹窗
const handleClose = (deno: () => void) => {
  handleCancel();
  deno();
};

// 添加菜单
const handleAddMenu = () => {
  menuTreeRef.value.open();
};

// 移除菜单
const handleDelMenu = () => {
  menuForm.value.parentId = undefined;
  parentMenuTagTitle.value = "";
};

// 暴露方法
defineExpose({
  open,
});
</script>

<template>
  <MenuTree @setParentMenu="setParentMenu" ref="menuTreeRef" :menuTree="props.menuTree" />

  <el-dialog :title="isEditor ? '修改' : '新增'" :before-close="handleClose" v-model="visible">

    <el-form ref="menuFormRef" :model="menuForm" label-position="right" label-width="90px">
      <el-row>
        <el-col :span="12">
          <el-form-item prop="parentId" label="父级菜单">
            <el-tag type="primary" v-if="menuForm.parentId" @close="handleDelMenu" closable>{{ parentMenuTagTitle
            }}</el-tag>
            <el-button v-else @click="handleAddMenu" size="small" plain>
              <MyIcon icon="el:Plus" color="#ff00ff" />
            </el-button>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item prop="sort" label="排序" :rules="[{ required: true, message: '请输入排序' }]">
            <el-input-number :min="0" :precision="0" v-model="menuForm.sort" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item prop="meta.title" label="菜单标题" :rules="[{ required: true, message: '请输入标题' }]">
        <el-input v-model="menuForm.meta.title" placeholder="请输入标题" />
      </el-form-item>
      <el-row>
        <el-form-item prop="meta.menuType" label="菜单类型" :rules="[{ required: true, message: '请选择菜单类型' }]">
          <el-radio-group :disabled="disableMenuTypeChange" v-model="menuForm.meta.menuType">
            <el-radio value="catalog">目录</el-radio>
            <el-radio value="menu">菜单</el-radio>
            <el-radio value="url">外链</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-row>
      <el-form-item v-if="menuForm.meta.menuType !== 'url'" prop="name" label="路由名称"
        :rules="[{ required: true, message: '请输入路由名称' }]">
        <el-input v-model="menuForm.name" placeholder="请输入路由名称" />
      </el-form-item>
      <el-form-item prop="path" label="路由路径" :rules="[{ required: true, message: '请输入路径' }]">
        <el-input v-model="menuForm.path" placeholder="请输入路由路径或外链路径" />
      </el-form-item>
      <el-form-item prop="redirect" label="重定向路径">
        <el-input v-model="menuForm.redirect" placeholder="请输入重定向路径" />
      </el-form-item>
      <el-form-item prop="component" label="组件路径" v-if="menuForm.meta.menuType === 'menu'">
        <el-autocomplete :fetch-suggestions="SearchComponentPaths" v-model="(menuForm.component as any)" clearable
          placeholder="请输入组件路径">
          <template #prefix> src/views </template>
          <template #suffix> .vue </template>
        </el-autocomplete>
      </el-form-item>
      <el-row>
        <el-col :span="12">
          <el-form-item prop="meta.icon" label="菜单图标">
            <el-input v-model="menuForm.meta.icon" placeholder="请输入菜单图标" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item prop="meta.hidden" label="是否隐藏">
            <el-switch :active-value="1" :inactive-value="0" v-model="menuForm.meta.hidden" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleCancel">取消</el-button>
        <el-button type="primary" @click="handleOk">
          {{ isEditor ? "提交修改" : "添加" }}
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style lang="less" scoped>
:deep(.is-tow-children) {
  .el-tree-node__content {
    color: #626aef;
  }
}

:deep(.menu-tree) {
  .is-tow-children {
    .el-tree-node__children {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
    }
  }
}
</style>
